package com.riteny.common.schedule.service;

import com.riteny.common.schedule.entity.ScheduleTask;
import com.riteny.common.schedule.entity.Task;
import com.riteny.common.schedule.exception.ScheduleTaskException;
import com.riteny.common.schedule.util.ScheduleTaskPool;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

/**
 * @author Riteny
 * 2020/9/25  14:54
 */
public class ScheduleAgentService {

    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    public ScheduleAgentService(ThreadPoolTaskScheduler threadPoolTaskScheduler) {
        this.threadPoolTaskScheduler = threadPoolTaskScheduler;
    }

    /**
     * 提交一個定時任務
     *
     * @param taskName 任務名稱
     * @param cron     cron時間表達式
     * @param task     任務詳細執行内容，需繼承runnable接口
     */
    public void addScheduleTask(String taskName, String cron, Runnable task) {

        threadPoolTaskScheduler.setPoolSize(threadPoolTaskScheduler.getPoolSize() + 1);

        ScheduledFuture future = threadPoolTaskScheduler.schedule(task, new CronTrigger(cron));

        ScheduleTask scheduleTask = new ScheduleTask(taskName, cron, task, future);

        ScheduleTaskPool.add(taskName, scheduleTask);
    }

    /**
     * 停止並移除任務
     *
     * @param taskName 任務名稱
     */
    public void removeScheduleTask(String taskName) throws ScheduleTaskException {

        ScheduleTaskPool.remove(taskName);

        if (threadPoolTaskScheduler.getPoolSize() > 1) {
            threadPoolTaskScheduler.setPoolSize(threadPoolTaskScheduler.getPoolSize() - 1);
        }
    }

    /**
     * 停止任務
     *
     * @param taskName 任務名稱
     */
    public void stopScheduleTask(String taskName) throws ScheduleTaskException {
        ScheduleTaskPool.stop(taskName);
    }

    /**
     * 啓動任務
     *
     * @param taskName 任務名稱
     */
    public void startScheduleTask(String taskName) throws ScheduleTaskException {

        ScheduleTask scheduleTask = ScheduleTaskPool.get(taskName);

        ScheduledFuture future = threadPoolTaskScheduler.schedule(scheduleTask.getTask(), new CronTrigger(scheduleTask.getCron()));

        scheduleTask.setFuture(future);
    }

    /**
     * 重新啓動任務
     *
     * @param taskName 任務名稱
     * @param cron     cron時間表達式
     */
    public void restartScheduleTask(String taskName, String cron) throws ScheduleTaskException {

        ScheduleTask scheduleTask = ScheduleTaskPool.get(taskName);

        stopScheduleTask(taskName);

        scheduleTask.setCron(cron);

        startScheduleTask(taskName);
    }

    public List<Task> getScheduleTaskList() {

        List<Task> tasks = new ArrayList<>();

        Map<String, ScheduleTask> scheduleTasks = ScheduleTaskPool.getScheduleTasks();

        scheduleTasks.forEach((name, scheduleTask) -> {
            Task task = new Task();
            task.setName(name);
            task.setCron(scheduleTask.getCron());
            task.setIsCancel(scheduleTask.getFuture().isCancelled());
            tasks.add(task);
        });

        return tasks;
    }

    public ScheduleTask getScheduleTask(String taskName) throws ScheduleTaskException {
        return ScheduleTaskPool.get(taskName);
    }
}
